package hci;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;

import main.ChatSystem;
import observerNotification.ErrorObserverNotification;


/**
 * Generates the HCI of a conversation
 * 
 * <p>
 * <ul>
 * <li>Project: 	ChatSystemG3</li>
 * <li>Called by: 	ChatGUI</li>
 * </ul>
 * </p>
 * 
 * @author COMBES Nicolas - LECHANTRE Arnaud
 * @see JFrame
 * @see ActionListener
 * @see ChatGui
 */
@SuppressWarnings("serial")
public class ChatingFrame extends JFrame implements ActionListener {

	/*
	 * GUI attributes
	 */
	/**
	 * Displays the message history
	 */
	private JTextPane textHistory;				//Zone that displays the history of the messages
	
	/**
	 * Label for typing zone
	 */
	private JLabel lblTypeZone;					//Label that announce the typing zone 
	/**
	 * Typing zone
	 */
	private TextArea textTypeZone;				//Zone where the user should type the messages
	
	/**
	 * Send button
	 */
	private JButton btnSend;					//button that the user should press to send a message
	
	/**
	 * Controller of the application (see MVC pattern)
	 */
	private FromUser chatGUI;					//Controller of the application (see MVC pattern)
	
	/**
	 * Label containning notifications
	 */
	private JLabel lblNotif;					//Label that displays the notifications
	
	/**
	 * Frame layout
	 */
	private GridBagLayout layout;				//Layout of the frame
	
	/*
	 * Coloring history attributes
	 */
	/**
	 * Style field
	 */
	private Style messageStyle;					//Style used to display the messages
	/**
	 * Style field
	 */
	private Style usernameStyle;				//Style used to display the user names
	/**
	 * Style field
	 */
	private Style yourNameStyle;				//unused for the moment but could be used to display the local user name in a different color
	/**
	 * Style field
	 */
	private int historyCursor;					//Cursor that mark the end of the last displayed message (use for adding messages)
	/**
	 * Style field
	 */
	private String lastSender;					//name of the last displayed sender (in order to damn redundancy) 
	
	/*
	 * Other atribute
	 */
	/**
	 * Unique conv id
	 */
	private int convId;							//Unique id of the conversation set by the model
	private String localUserName;				//Name of the local user
	/**
	 * Menu bar used to close a conv or send a file
	 */
	private ChatingFrameMenuBar menuBar;		//Menu bar enabling to send a file or close the conversation
	
	/**
	 * construct; Creates all the interface
	 * @param convId Unique identifier of the conversation set by the model
	 * @param chatGUI Controller of the application 
	 * @param userList list of users
	 * @param localUsername String
	 */
	public ChatingFrame(int convId, FromUser chatGUI, Object[] userList, String localUsername) {
		super();
		this.chatGUI = chatGUI;
		this.convId=convId;
		this.localUserName = localUsername;
		this.lastSender="";
		
		//We create a string containing all the user names separated by a comma
		String fname= userList[0].toString();
		for(int i=1;i<userList.length;i++){
			fname +=", " + userList[i];
		}
		//if debug mode is activated we display it
		if(ChatSystem.debugMode)System.out.println("hci.ChatingFrame: Creation of the view of conversation number "+convId +" with users : "+fname +" You are: "+this.localUserName);
		//and use this string as a frame name
		this.setTitle(fname);
		
		
		/* ----------------------------------------------
		 *       Initialize the frame fields
		 *///-------------------------------------------
		
		//textHistory
		this.textHistory= new JTextPane();
		this.textHistory.setBackground(Color.white);	//set background to white
		this.textHistory.setEditable(false);			//set not editable
		
		//lblTypeZone
		this.lblTypeZone= new JLabel(ChatGui.strings.getString("sendingAreaPromptTxt"));
		
		//textTypeZone
		this.textTypeZone= new TextArea();
		
		//lblNotif
		this.lblNotif = new JLabel (ChatGui.strings.getString("notifConversationEstablishedTxt"));
		this.lblNotif.setForeground(Color.GRAY);		//Set text color to Gray
		
		//send button
		this.btnSend= new JButton(ChatGui.strings.getString("sendBtnText"));
		this.btnSend.addActionListener(this);			//add a listener to the button
		
		/*------------------------------------------------
		 * 					Fill window
		 *///--------------------------------------------
		//initialize the layout
		this.layout = new GridBagLayout();
		this.setLayout(layout);
		
		
		//we initialize the constraint
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.BOTH; //We choose to fill totaly the rows
		//set the position
		c.gridx = 0;
		c.gridy = 0;
		//And we want set the width
		c.gridwidth=10;
		//We create a scroll pane to contain the text history
		JScrollPane scroll= new JScrollPane(textHistory);
		//As we are going to add a scroll pane we set a weight
		c.weightx=1;
		c.weighty=2;
		//And we finaly add it
		this.add(scroll, c);
		
		//We are no longer going to add some scrolls so we unset the weight
		c.weightx=0;
		c.weighty=0;
		
		//We set the lblNotif position and width 
		c.gridy++;
		c.gridx=4;
		c.gridwidth=6;
		//and add the lblNotif
		this.add(this.lblNotif,c);
		
		//We set the lblTypeZone position and width 
		c.gridy++;
		c.gridx=0;
		c.gridwidth=10;
		//and we add it
		this.add(lblTypeZone,c);
		
		//We set the textTypeZone position and width 
		c.gridx=0;
		c.gridy++;
		c.gridwidth=9;
		//and we add it
		this.add(textTypeZone, c);
		
		//We set the btnSend position and width 
		c.gridx=9;
		c.gridwidth=1;
		c.fill= GridBagConstraints.NONE;
		//and we add it
		this.add(btnSend,c);
		
		
		
		//and display the window
		this.setSize(new Dimension(600,400));
		
		
		
		/*--------------------------------------------
		 * 			We add some Color :)
		 *///-----------------------------------------
		
		//To the window
		this.getContentPane().setBackground(new Color(203, 231, 245));
		
		//And to the display zone
		this.messageStyle = this.textHistory.getStyle("default");
		this.usernameStyle = this.textHistory.addStyle("username",this.messageStyle);
		StyleConstants.setFontFamily(usernameStyle, "Comic sans MS");
		StyleConstants.setFontSize(usernameStyle, 16);
		StyleConstants.setForeground(usernameStyle, Color.BLUE);
		this.yourNameStyle = this.textHistory.addStyle("yourName", usernameStyle);
		StyleConstants.setForeground(yourNameStyle, Color.RED);
		StyleConstants.setFontSize(yourNameStyle, 16);
		
		//We also set the variables used to ameliorate the history window
		this.historyCursor=0;
		this.lastSender="a";
		
		this.menuBar= new ChatingFrameMenuBar(this.chatGUI, this);
		this.setJMenuBar(menuBar);
		this.setVisible(true);
	}
	
	
	
	/**
	 * Changes the notificiation in the notification label 
	 * 
	 * @param notif : message to put in the lblNotif
*/
	public void getNotification(String notif){
		this.lblNotif.setText(notif);
	}
	
	/**
	 * Show the message in the conversation history
	 * @param username : Name of the sender of the message
	 * @param content : content of the message
	 * 
	 * 
	 */
	 public void showMessage(String username, String content){
		//1st we check if the message was send by the same user that the last displayed one
		 if ( ! this.lastSender.equals(username)){
			//if not, we change the lastSender name
			this.lastSender=username;
			
			//We prepare the username to be displayed
			username+=" :\n";
			try {
				//And displays it (With color please :) )
				this.textHistory.getStyledDocument().insertString(this.historyCursor, username, this.usernameStyle);
			} catch (BadLocationException e) {
				e.printStackTrace();
			}
			//We actualize the history cursor (otherwise future message would erase this one)
			this.historyCursor+= username.length();
		}
		
		//Then we prepares the message to be displayed
		content+="\n";
		try {
			//and displays it
			this.textHistory.getStyledDocument().insertString(this.historyCursor, content, this.messageStyle);
			//we do not forget to actualize the cursor
			this.historyCursor+= content.length();
		} catch (BadLocationException e) {
			e.printStackTrace();
		}
		//if conversation is closed, we reoppen it
		if(!this.isVisible()||!this.isActive()){
			this.setVisible(true);
		}
		this.textHistory.setCaretPosition(this.textHistory.getDocument().getLength());
	}

	 /**
	  * Used on Send button
	  * @see ActionListener
	  */
	@Override
	public void actionPerformed(ActionEvent arg0) {
		if(arg0.getSource().equals(this.btnSend)){
			//if the received action is comming from a button
			//We ask the controller to manage the event
			this.getNotification(ChatGui.strings.getString("notifSendingMessageTxt"));
			this.chatGUI.sendMessage(this.convId, this.textTypeZone.getText());
			
			//For the moment we displays the lessage but this would eventually not be done there later
			this.showMessage(this.localUserName, this.textTypeZone.getText());
			
			//We empty the typing zone
			this.textTypeZone.setText("");
			
		} 
	}

	/**
	 * Displays the notification in the notification label
	 * 
	 * @param notification message to be displayed in the notification label
	 */
	public void showNotification(String notification) {
		this.lblNotif.setText(notification);
	}

	/**
	 * Opens a dialog box to display the error
	 * @param e error to display
	 */
	public void showError(ErrorObserverNotification e) {
		JOptionPane.showMessageDialog(this,e.getMessage(),ChatGui.strings.getString("errorDialogNameTxt"),JOptionPane.ERROR_MESSAGE);
	}

	/**
	 * getConvId
	 * @return the identifier of the conversation
	 */
	public int getConvId() {
		return this.convId;
	}

	/**
	 * Asks user if they do accept the file request. If answer is yes,  requesst a folder to save the file.
	 * @param sender username of the sender
	 * @param fileName name of the file to be transfered
	 * @param fileSize size of the file to be transfered
	 */
	public void showFileRequest(String sender, String fileName, long fileSize) {
		int res= JOptionPane.showConfirmDialog(this,sender +" "+ ChatGui.strings.getString("questionFileRequestTxt") + "\n" +
					ChatGui.strings.getString("questionFileNameTxt")+ " :" + fileName + "\n"+
					ChatGui.strings.getString("questionFileSizeTxt")+ " :" + fileSize +
					ChatGui.strings.getString("questionFileBitTxt")+" \n" +
					ChatGui.strings.getString("questionFileQuestionTxt") ,
				ChatGui.strings.getString("questionFileDialogNameTxt"),JOptionPane.YES_NO_OPTION);
		if(res==JOptionPane.CANCEL_OPTION || res==JOptionPane.CLOSED_OPTION ||res==JOptionPane.NO_OPTION ){
		    this.chatGUI.answerFileRequest(this.getConvId(), false, fileName, null);
		}else if (res==JOptionPane.YES_OPTION){
			JFileChooser fileChooser = new JFileChooser();
			fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			if (fileChooser.showOpenDialog(this)== JFileChooser.APPROVE_OPTION) {
				File f2=new File(fileChooser.getSelectedFile(), fileName);
				this.chatGUI.answerFileRequest(this.getConvId(), true, fileName,f2 );
			}
		}
	}

	/**
	 * Closes the chating frame
	 */
	public void close() {
		this.dispose();
	}



	/**
	 * Disables actions on chatting frame
	 */
	public void lock() {
		this.btnSend.setEnabled(false);
		this.textTypeZone.setEditable(false);
		this.menuBar.lock();
		this.lblNotif.setText(ChatGui.strings.getString("lblConnectionLostTxt"));
	}


	/**
	 * Enables actions on chatting frame
	 */
	public void unlock() {
		this.btnSend.setEnabled(true);
		this.textTypeZone.setEditable(true);
		this.menuBar.unlock();
		this.lblNotif.setText(ChatGui.strings.getString("notifConversationEstablishedTxt"));
	}

	
	
}
